home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
cpp_libs
/
varia
/
interp18.lha
/
interp-1.8
/
parser.y
< prev
next >
Wrap
Text File
|
1990-01-22
|
5KB
|
192 lines
%{
// parser.y --- a description of the grammar for the bison parser generator.
// Copyright (C) 1989 Carey Richard Murphey.
// (rich@rice.edu) 5310 Rutherglenn, Houston, TX 77096
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 1, or (at your option)
// any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#define YYDEBUG 1 /* 0 for no debugging, 1 for debugging */
#include <stream.h>
#include <math.h>
#include <ctype.h>
#include "parser.h"
extern "C" double pow(double, double);
enum declaration_enum {DOUBLE_TYPE, INT_TYPE};
declaration_enum declaration_type;
%}
%union {
double valu; /* float numbers. */
char * idnt; /* identifiers */
String * name; /* symbol names */
Node * nodp; /* AST node pointers */
Sym * symp; /* AST symbol pointers */
}
%token <valu> WHILE IF SYNTAXOF DOUBLE_DECL INT_DECL
%token <valu> NUM
%token <idnt> IDENT
%type <name> identifier
%type <nodp> expr statement statement_list
%type <nodp> declaration_list declaration_element declaration_start
%type <symp> sym new_symbol
%type <valu> eval_now
%right '='
%left '-' '+'
%left '*' '/'
%left NEG /* Negation--unary minus */
%left INCR DECR /* Increment (++) and Decrement (--) */
%right '^' /* Exponentiation */
%%
input:
/* empty */
| input eval_now
;
eval_now:
statement { $1->eval ();}
| error ';' { yyerror ("\tbad statement."); yyerrok;}
| ';' {}
;
statement:
sym '=' expr ';' { $$ = new Assign ($1, $3);}
| expr ';' { $$ = $1;}
| '{' { context.open ();}
statement_list '}' { $$ = $3; context.close ();}
| SYNTAXOF statement { $$ = $2; cerr << "\n// " << $2 << "\n";}
| WHILE '(' expr ')' statement
{ $$ = new While ($3, $5);}
| IF '(' expr ')' statement
{ $$ = new If ($3, $5);}
| declaration_list ';' { $$ = $1;}
;
statement_list:
statement { $$ = $1;}
| statement_list statement
{ $$ = new Statements ($1, $2);}
;
declaration_list:
declaration_start declaration_element
{ $$ = $2;}
| declaration_list ',' declaration_element
{ $$ = new Statements ($1, $3);}
;
declaration_element:
new_symbol '=' expr { $$ = new Assign ($1, $3);}
| new_symbol { $$ = $1;}
;
new_symbol:
identifier { if (context.top_level(*$1))
{
cerr << "\n// " << *$1
<< " is already defined.\n"; YYERROR;
}
else
{
Table t = context.top_table ();
switch (declaration_type)
{
case DOUBLE_TYPE:
(*t)[*$1] = new Double_Pointer (0.);
break;
case INT_TYPE:
(*t)[*$1] = new Int_Pointer (0);
break;
}
$$ = new Sym (*$1, t);
}
}
| identifier '(' { if (context.top_level(*$1))
{
cerr << "\n// " << *$1
<< " is already defined.\n"; YYERROR;
}
context.open ();
}
arg_list ')' { context.close ();
Table t = context.top_table ();
switch (declaration_type)
{
case DOUBLE_TYPE:
(*t)[*$1] = new Double_Function (0.);
break;
case INT_TYPE:
(*t)[*$1] = new Int_Function (0);
break;
}
$$ = new Sym (*$1, t);
}
;
arg_list:
arg_list { ;
Table t = context.top_table ();
$$ = $2;}
| DOUBLE_DECL identifier
{ ;
Table t = context.top_table ();
(*t)[*$1] = new Double_Pointer (0.);
}
| arg_list ',' arg_element
{ $$ = new Statements ($1, $3);}
;
arg_element:
new_symbol { $$ = $1;}
;
declaration_start:
DOUBLE_DECL { declaration_type = DOUBLE_TYPE;}
| INT_DECL { declaration_type = INT_TYPE;}
;
expr:
NUM { $$ = new Double ($1);}
| expr '+' expr { $$ = new Plus ($1, $3);}
| expr '-' expr { $$ = new Minus ($1, $3);}
| expr '*' expr { $$ = new Times ($1, $3);}
| expr '/' expr { $$ = new Divide ($1, $3);}
| '-' expr %prec NEG { $$ = new Uminus ($2);}
| expr '^' expr { $$ = new Pow ($1, $3);}
| sym INCR { $$ = new PostIncrement ($1);}
| sym DECR { $$ = new PostDecrement ($1);}
| INCR sym { $$ = new PreIncrement ($2);}
| DECR sym { $$ = new PreDecrement ($2);}
| identifier '(' expr ')'
{ if (!context.contains(*$1))
{
cerr << "\n// " << *$1
<< " is used but not declared.\n";
YYERROR;
}
else
$$ = new Func (new Sym (*$1,
context.table (*$1)), $3);}
| sym { $$ = $1;}
| '(' expr ')' { $$ = $2;}
| '(' error ')' { yyerror ("bad expression."); yyerrok;}
;
sym :
identifier { if (!context.contains(*$1))
{
cerr << "\n// " << *$1
<< " is used but not declared.\n";
YYERROR;
}
else
$$ = new Sym (*$1, context.table (*$1));}
;
identifier :
IDENT { $$ = new String ($1); /* delete after use! */}
;
%%